﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Pout_Porri.Screens.Interface;
using Pout_Porri.Objects;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Pout_Porri.Utils;
using Pout_Porri.Levels;

namespace Pout_Porri.Objects
{
    class Sonic : PhysicsGameEntity
    {
        private enum SonicStates
        {
            stand,
            standing,
            running,
            charging,
            walking,
            jumping,
            attacking,
            crouching,
            rolling,
        }

        private SonicStates currentState;
        private SpriteEffects spriteEffects;

        private const int MAX_JUMPS = 1;
        private int contJumps;
        private float jumpHeight;
        private int chargingVelocity = 400;
        Keys[] keys;


        /// <summary>
        /// The charged force
        /// </summary>
        private float force;
        private float timetoStandingAnimation = 0.0f;

        public Sonic(Texture2D image, Vector2 position, Vector2 velocity)
            : base(image, position, velocity, true)
        {
            Mass = 0.1f;
            contJumps = MAX_JUMPS;
            jumpHeight = 18f;
            DefaultVelocityX = velocity.X;
            MaxVelocityX = velocity.X * 5f;

            AccelerationX = 0.13f;
            spriteEffects = SpriteEffects.None;
            this.currentState = SonicStates.stand;

            configAnimations();
        }

        private void configAnimations()
        {
            Animation stand = new Animation(SonicStates.stand + "", new Vector2(40, 40), 150, 0, 0, 1, Axis.X);
            addAnimation(stand);

            Animation standing = new Animation(SonicStates.standing + "", new Vector2(40, 40), 150, 0, 0, 5, Axis.X);
            addAnimation(standing);

            Animation walking = new Animation(SonicStates.walking + "", new Vector2(40, 40), 80, 0, 1, 11, Axis.X);
            addAnimation(walking);

            Animation running = new Animation(SonicStates.running + "", new Vector2(40, 40), 80, 0, 2, 4, Axis.X);
            addAnimation(running);

            Animation crouching = new Animation(SonicStates.crouching + "", new Vector2(40, 40), 80, 1, 3, 2, Axis.X);
            addAnimation(crouching);

            Animation charging = new Animation(SonicStates.charging + "", new Vector2(40, 40), 40, 0, 4, 5, Axis.X);
            addAnimation(charging);

            Animation jumping = new Animation(SonicStates.jumping + "", new Vector2(40, 40), 50, 3, 3, 5, Axis.X);
            addAnimation(jumping);

            Animation rolling = new Animation(SonicStates.rolling + "", new Vector2(40, 40), 40, 3, 3, 5, Axis.X);
            addAnimation(rolling);

            Animation attacking = new Animation(SonicStates.attacking + "", new Vector2(77, 43), 160, 0, 6, 3, Axis.X);
            addAnimation(attacking);

            setCurrentAnimation(currentState + "");
        }

        public void handleInput()
        {
            if (currentState == SonicStates.charging)
            {
                charge();
                if (Game1.keyboardState.IsKeyUp(Keys.Down))
                {
                    currentState = SonicStates.rolling;
                    AccelerationX += force;
                    isRunning = true;
                }
            }
            else
            {
                if (currentState != SonicStates.rolling && currentState != SonicStates.attacking && currentState != SonicStates.jumping)
                {
                    currentState = SonicStates.stand;
                    this.direction.X = 0;
                    //AccelerationX = 0.13f;
                    isRunning = false;
                }
                else if (currentState != SonicStates.rolling && currentState != SonicStates.attacking && currentState != SonicStates.jumping)
                {
                    currentState = SonicStates.standing;
                    this.direction.X = 0;

                    isRunning = false;
                }
            }
            
            keys = Game1.keyboardState.GetPressedKeys();
            
            if (Keyboard.GetState().IsKeyDown(Keys.Right) || Keyboard.GetState().IsKeyDown(Keys.Left))
            {
                if (currentState != SonicStates.rolling && currentState != SonicStates.jumping)
                    currentState = SonicStates.walking;
                this.direction.X = (Keyboard.GetState().IsKeyDown(Keys.Right)) ? 1 : -1;
                isRunning = true;
                if (AccelerationX >= 400)
                {
                    currentState = SonicStates.running;
                }
            }
            else if (Keyboard.GetState().IsKeyDown(Keys.Down))
            {
                if (currentState != SonicStates.rolling && currentState != SonicStates.charging && currentState != SonicStates.jumping)
                {
                    currentState = SonicStates.crouching;
                }
            }

                // o Else If abaixo manda atacar
            else if (Game1.keyboardState.IsKeyDown(Keys.Space) && !Game1.previusKeyboardState.IsKeyDown(Keys.Space))
            {
                if (currentState != SonicStates.rolling && currentState != SonicStates.jumping)
                {
                    currentState = SonicStates.attacking;                    
                }
            }
            // o if abaixo verifica se a animação está acabada e manda parar
            if (this.isAnimationFinished() && currentState == SonicStates.attacking)
            {
                currentState = SonicStates.stand;
            }

            if (Game1.keyboardState.IsKeyDown(Keys.Up) && !Game1.previusKeyboardState.IsKeyDown(Keys.Up))
            {
                if (contJumps > 0)
                {
                    contJumps--;
                    currentState = SonicStates.jumping;
                    this.Velocity = new Vector2(this.Velocity.X, -jumpHeight);
                    this.setGrounded(false);
                }
            }
            
            // combos
            if (keys.Length > 1)
            {
                if ((keys[0] == Keys.Down && keys[1] == Keys.LeftShift))
                {
                    currentState = SonicStates.charging;
                }
            }
            
            if (spriteEffects == SpriteEffects.None && direction.X == -1)
            {
                spriteEffects = SpriteEffects.FlipHorizontally;
            }
            else if (spriteEffects == SpriteEffects.FlipHorizontally && direction.X == 1)
            {
                spriteEffects = SpriteEffects.None;
            }

        }

        public override void setGrounded(bool b)
        {
            base.setGrounded(b);
            if (b == true)
            {
                contJumps = MAX_JUMPS; // reset the jumps
                if (currentState == SonicStates.jumping)
                {
                    if (AccelerationX < 399)
                    {
                        currentState = SonicStates.stand;
                    }
                    if (AccelerationX >= 399)
                    {
                        currentState = SonicStates.running;
                    }
                    force = 0;
                }
            }
        }

        private void charge()
        {
            if (force < 40)
            {
                force += 0.5f;
            }
        }

        public override void update(GameTime gameTime)
        {
            handleInput();
            this.applyGravity(gameTime);
            if (this.position.Y >= 200)
            {
                setGrounded(true);
                this.position.Y = 200;
            }
            // this.applyMovement(gameTime);
            
            // dx += vX * gameTime.ElapsedGameTime.TotalMilliseconds

            // x += v0 + 0.5f * a * Math.Pow(gameTime.ElapsedGameTime.TotalMilliseconds/1000, 2)
            this.position.X += direction.X * (velocity.X * (float)gameTime.ElapsedGameTime.TotalMilliseconds / 1000f) + (0.5f * (AccelerationX * direction.X) * (float)Math.Pow(gameTime.ElapsedGameTime.TotalMilliseconds / 1000, 2));

            //velocity.X += (0.5f * direction.X *-1);
            if (currentState == SonicStates.rolling)
            {
                if (velocity.X == 0)
                {
                    currentState = SonicStates.stand;
                    velocity.X = 200;
                }
                else if (velocity.X > 0)
                {
                    velocity.X -= 0.5f;
                }
                else
                {
                    velocity.X += 0.5f;
                }
            }
            // Resolvido questão de correr ou não
            if (currentState == SonicStates.walking)
            {
                AccelerationX += 5f;

            }
            if (currentState == SonicStates.stand)
            {
                AccelerationX = 0.0f;

            }
            if (currentState == SonicStates.jumping)
            {
                AccelerationX = 399.0f; 
            }
            if (currentState == SonicStates.charging)
            {
                this.velocity.X = chargingVelocity;
            }
            
            //checkMatrixCollisionInX();
            checkMatrixCollisionInY();

            setCurrentAnimation(currentState + "");
            // Tive que anular o Standing por enquanto, esse estado está atrapalhando os outros por motivos desconhecidos. 

            //if (currentState == SonicStates.stand)
            //{
            //    timetoStandingAnimation += (float)gameTime.ElapsedGameTime.Milliseconds;
            //}
            //if (timetoStandingAnimation > 1000)
            //{
            //    currentState = SonicStates.standing;
            //}

            Game1.window.Title = "" + AccelerationX;

            // posso fazer uma concatenacao com uma string vazia que o enum sera convertido para string
            if (currentState == SonicStates.rolling)
            {
                if (spriteEffects == SpriteEffects.None)
                {
                    direction.X = 1;
                }
                else
                {
                    direction.X = -1;
                }
            }       

            base.update(gameTime);
        }

        public override void draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(getImage(), position, sourceRectangle, Color.White, 0f, Vector2.Zero,1, spriteEffects, 0);
        }
    }
}
